package com.arrogames.rgblabyrinth.game.rendering {
	import ash.core.Engine;
	import ash.core.System;
	
	import com.arrogames.lib.ash.rendering.RenderNode;
	import com.arrogames.lib.ash.rendering.RenderingSystem;
	
	import flash.utils.Dictionary;
	
	import org.as3commons.logging.api.ILogger;
	import org.as3commons.logging.api.getLogger;
	
	import starling.display.DisplayObject;
	import starling.display.DisplayObjectContainer;
	import starling.display.Sprite;
	
	public class LayeringSystem extends RenderingSystem {
		
		private static var LOG:ILogger = getLogger(LayeringSystem);
		
		private var layers:Dictionary;
		
		public function LayeringSystem(container:DisplayObjectContainer) {
			super(container);
			layers = new Dictionary();
		}
		
		override public function update(time:Number):void {
			super.update(time);
			var node:RenderNode;
			for (node = nodes.head; node; node = node.next) {
				updateLayerFor(node);
			}
		}
		
		override protected function renderNodeAdded(node:RenderNode):void {
			var layer:DisplayObjectContainer = getLayer(node.position.z); 
			layer.addChild(node.display.graphic);
		}
		
		override protected function renderNodeRemoved(node:RenderNode):void {
			var layer:DisplayObjectContainer = getLayer(node.position.z); 
			layer.removeChild(node.display.graphic);
		}
		
		private function updateLayerFor(node:RenderNode):void {
			var layer:DisplayObjectContainer = getLayer(node.position.z);
			if (!layer.contains(node.display.graphic)) {
				var oldLayer:DisplayObjectContainer = getLayerFor(node.display.graphic);
				layer.removeChild(node.display.graphic);
				oldLayer.addChild(node.display.graphic);
				LOG.debug("Moved layer for graphic.");
			}
		}
		
		private function getLayer(layer:Number):DisplayObjectContainer {
			if (layers[layer] == undefined) {
				var layerContainer:Sprite = new Sprite();
				layers[layer] = layerContainer;
				container.addChildAt(layerContainer, layer);
				LOG.debug("Created new layer {0}.", [layer]);
			}
			return layers[layer];
		}
		
		private function getLayerFor(graphic:DisplayObject):DisplayObjectContainer {
			var result:DisplayObjectContainer;
			for (var k:Object in layers) {
				var value:DisplayObjectContainer = layers[k] as DisplayObjectContainer;
				if (value.contains(graphic)) {
					result = value;
					LOG.debug("Found layer {0} for requested graphic.", [k.toString()]);
					break;
				}
			}
			return result;
		}
		
	}
}